package com.ffcc.fitness.gym.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import com.ffcc.fitness.base.exception.ServiceException;
import com.ffcc.fitness.base.response.JsonResult;
import com.ffcc.fitness.base.response.StatusCode;
import com.ffcc.fitness.gym.pojo.dto.GymSaveParam;
import com.ffcc.fitness.gym.pojo.dto.GymClaimParam;
import com.ffcc.fitness.gym.pojo.dto.POIGymParam;
import com.ffcc.fitness.gym.pojo.vo.GymInfo;
import com.ffcc.fitness.gym.service.GymService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;
import java.util.List;
import java.util.UUID;

@Slf4j
@RestController
@RequestMapping("v1/gym/")
public class GymController {
    
    @Autowired
    private GymService gymService;

    @Value("${file-path}")
    private String dirPath;    @SaIgnore
    @PostMapping("insert")
    public JsonResult insert(@RequestBody GymSaveParam gymSaveParam) {
        log.info("创建场馆参数: {}", gymSaveParam);
        gymService.insert(gymSaveParam);
        return JsonResult.ok();
    }

    @SaIgnore
    @GetMapping("getByUserId")
    public JsonResult getByUserId(@RequestParam Long userId) {
        GymInfo gymInfo = gymService.getGymByUserId(userId);
        return JsonResult.ok(gymInfo);
    }
      /**
     * 根据用户ID获取已认领的场馆信息
     * @param userId 用户ID
     * @return 认领的场馆信息
     */
    @SaCheckLogin
    @GetMapping("owner/{userId}")
    public JsonResult getClaimedGymByUserId(@PathVariable Long userId) {
        log.info("获取用户认领的场馆信息, userId: {}", userId);
        
        // 确保用户只能查询自己的认领信息
        Long currentUserId = StpUtil.getLoginIdAsLong();
        if (!currentUserId.equals(userId)) {
            log.warn("用户{}尝试查询其他用户{}的场馆信息", currentUserId, userId);
            return new JsonResult(StatusCode.NO_PERMISSION);
        }
        
        GymInfo gymInfo = gymService.getClaimedGymByUserId(userId);
        if (gymInfo == null) {
            log.info("用户{}还没有认领任何场馆", userId);
            return JsonResult.ok(null); // 返回成功状态但数据为null
        }
        
        log.info("成功获取用户{}认领的场馆信息: {}", userId, gymInfo.getName());
        return JsonResult.ok(gymInfo);
    }
    
    @SaIgnore
    @GetMapping("selectByUsername")
    public JsonResult selectByUsername(@RequestParam String username) {
        GymInfo gymInfo = gymService.selectByUsername(username);
        return JsonResult.ok(gymInfo);
    }
      /**
     * 认领场馆
     * @param gymClaimParam 认领参数，包含场馆ID、用户ID、邮箱、验证码等
     * @return 认领结果
     */
    @SaCheckLogin
    @PostMapping("claim")
    public JsonResult claim(@RequestBody GymClaimParam gymClaimParam) {
        log.info("场馆认领请求：{}", gymClaimParam);
        
        // 从Sa-Token中获取当前登录用户ID，确保安全性
        Long currentUserId = StpUtil.getLoginIdAsLong();
        gymClaimParam.setUserId(currentUserId);
          gymService.claimGym(gymClaimParam);
        return JsonResult.ok();
    }    /**
     * 发送验证码到邮箱
     * @param email 邮箱地址
     * @return 发送结果
     */
    @SaIgnore
    @PostMapping("sendVerificationCode")
    public JsonResult sendVerificationCode(@RequestParam String email) {
        log.info("发送验证码到邮箱: {}", email);
        try {
            boolean result = gymService.sendVerificationCode(email);
            if (result) {
                return JsonResult.ok("验证码已发送");
            } else {
                return new JsonResult(5001, "验证码发送失败，请稍后重试");
            }
        } catch (Exception e) {
            log.error("发送验证码异常", e);
            return new JsonResult(5001, "验证码发送失败");
        }
    }

    /**
     * 获取当前用户邮箱
     * @return 用户邮箱
     */
    @SaCheckLogin
    @GetMapping("getUserEmail")
    public JsonResult getUserEmail() {
        try {
            Long userId = StpUtil.getLoginIdAsLong();
            String email = gymService.getUserEmail(userId);
            return JsonResult.ok(email);        } catch (Exception e) {
            log.error("获取用户邮箱失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }

    /**
     * 验证邮箱验证码
     * @param email 邮箱
     * @param code 验证码
     * @return 验证结果
     */
    @SaCheckLogin
    @PostMapping("verifyCode")
    public JsonResult verifyCode(@RequestParam String email, @RequestParam String code) {
        try {
            boolean isValid = gymService.verifyEmailCode(email, code);
            return JsonResult.ok(isValid);        } catch (Exception e) {
            log.error("验证邮箱验证码失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }
    
    /**
     * 批量存储POI场馆数据
     * @param poiGyms POI场馆列表
     * @return 存储结果
     */
    @SaIgnore
    @PostMapping("savePOIGyms")
    public JsonResult savePOIGyms(@RequestBody List<POIGymParam> poiGyms) {
        try {
            log.info("接收POI场馆数据，数量: {}", poiGyms.size());
            int savedCount = gymService.savePOIGyms(poiGyms);
            return JsonResult.ok(savedCount);        } catch (Exception e) {
            log.error("存储POI场馆数据失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }
    
    /**
     * 获取未认领的POI场馆列表
     * @return 未认领场馆列表
     */
    @SaIgnore
    @GetMapping("getUnclaimedPOIGyms")
    public JsonResult getUnclaimedPOIGyms() {
        try {
            List<GymInfo> gyms = gymService.getUnclaimedPOIGyms();
            return JsonResult.ok(gyms);
        } catch (Exception e) {
            log.error("获取未认领POI场馆失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }
    
    /**
     * 获取所有POI场馆列表（包括已认领和未认领）
     * @return 所有POI场馆列表
     */
    @SaIgnore
    @GetMapping("getAllPOIGyms")
    public JsonResult getAllPOIGyms() {
        try {
            List<GymInfo> gyms = gymService.getAllPOIGyms();
            return JsonResult.ok(gyms);
        } catch (Exception e) {
            log.error("获取所有POI场馆失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }
    
    /**
     * 根据区域获取场馆列表
     * @param area 区域名称
     * @return 场馆列表
     */
    @SaIgnore
    @GetMapping("getGymsByArea")
    public JsonResult getGymsByArea(@RequestParam String area) {
        try {
            List<GymInfo> gyms = gymService.getGymsByArea(area);
            return JsonResult.ok(gyms);        } catch (Exception e) {
            log.error("根据区域获取场馆列表失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }
    
    /**
     * 获取附近场馆
     * @param centerLng 中心经度
     * @param centerLat 中心纬度
     * @param radius 搜索半径（公里）
     * @return 附近场馆列表
     */
    @SaIgnore
    @GetMapping("getNearbyGyms")
    public JsonResult getNearbyGyms(@RequestParam Double centerLng, 
                                   @RequestParam Double centerLat, 
                                   @RequestParam(defaultValue = "5.0") Double radius) {
        try {
            List<GymInfo> gyms = gymService.getNearbyGyms(centerLng, centerLat, radius);
            return JsonResult.ok(gyms);        } catch (Exception e) {
            log.error("获取附近场馆失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }    /**
     * 检查场馆是否可认领
     * @param gymId 场馆ID或POI ID
     * @return 是否可认领
     */
    @SaIgnore
    @GetMapping("isClaimable")
    public JsonResult isClaimable(@RequestParam String gymId) {
        boolean claimable = gymService.isClaimable(gymId);
        return JsonResult.ok(claimable);
    }

    /**
     * 场馆模块专用的多图片上传方法
     * 支持一次性上传最多10张图片，并保存在 gym 文件夹中
     */
    @SaIgnore
    @PostMapping("upload")
    public JsonResult upload(@RequestParam("files") List<MultipartFile> files) throws IOException {
        // 验证上传图片数量是否超过10张
        if (files.size() > 10) {
            return new JsonResult(StatusCode.FILE_UPLOAD_MAX_COUNT);
        }

        List<String> fileUrls = new ArrayList<>();

        // 创建 gym 专用文件夹
        File gymDir = new File(dirPath + "/gym");
        if (!gymDir.exists()) {
            gymDir.mkdirs();
        }        // 处理每一个上传的文件
        for (MultipartFile file : files) {
            // 得到原始文件名
            String fileName = file.getOriginalFilename();
            if (fileName == null || fileName.isEmpty()) {
                continue; // 跳过无效文件
            }
            // 获取文件后缀
            String suffix = fileName.substring(fileName.lastIndexOf("."));
            // 创建唯一的文件名
            String newFileName = UUID.randomUUID().toString() + suffix;
            // 完整的文件保存路径
            String filePath = dirPath + "/gym/" + newFileName;

            // 保存文件
            file.transferTo(new File(filePath));
            // 保存相对路径，用于前端展示
            fileUrls.add("/gym/" + newFileName);
        }        return JsonResult.ok(fileUrls);
    }
    
    /**
     * 更新场馆状态
     * @param gymId 场馆ID
     * @param status 新状态
     * @return 更新结果
     */
    @PutMapping("/{gymId}/status")
    public JsonResult updateGymStatus(@PathVariable Long gymId, 
                                     @RequestBody Map<String, String> statusRequest) {
        try {
            // 验证用户权限 - 只有场馆拥有者才能更新状态
            String token = StpUtil.getTokenValue();
            if (token == null) {
                return new JsonResult(StatusCode.NOT_LOGIN);
            }
            
            Long currentUserId = StpUtil.getLoginIdAsLong();
            String newStatus = statusRequest.get("status");
            
            if (newStatus == null || newStatus.trim().isEmpty()) {
                return new JsonResult(StatusCode.PARAMETER_ERROR, "状态不能为空");
            }
            
            // 验证状态值有效性
            if (!"open".equals(newStatus) && !"closed".equals(newStatus)) {
                return new JsonResult(StatusCode.PARAMETER_ERROR, "无效的状态值");
            }
            
            gymService.updateGymStatus(gymId, currentUserId, newStatus);
            return JsonResult.ok();
            
        } catch (ServiceException e) {
            log.error("更新场馆状态失败", e);
            return new JsonResult(e.getStatusCode());
        } catch (Exception e) {
            log.error("更新场馆状态失败", e);
            return new JsonResult(StatusCode.OPERATION_FAILED);
        }
    }

    /**
     * 删除已上传的场馆图片
     */
    @SaIgnore
    @PostMapping("remove")
    public JsonResult remove(@RequestParam("imgUrls") List<String> imgUrls) {
        for (String imgUrl : imgUrls) {
            // 删除每个图片文件
            new File(dirPath + imgUrl).delete();
        }
        return JsonResult.ok();
    }
}
